home *** CD-ROM | disk | FTP | other *** search
- /*------------------------------------------------------------------*/
- /* */
- /* MC68000 Cross Assembler */
- /* */
- /* Copyright (c) 1985 by Brian R. Anderson */
- /* */
- /* Operand processor - May 31, 1987 */
- /* */
- /* This program may be copied for personal, non-commercial use */
- /* only, provided that the above copyright notice is included */
- /* on all copies of the source code. Copying for any other use */
- /* without the consent of the author is prohibited. */
- /* */
- /*------------------------------------------------------------------*/
- /* */
- /* Originally published (in Modula-2) in */
- /* Dr. Dobb's Journal, April, May, and June 1986. */
- /* */
- /* AmigaDOS conversion copyright (c) 1987 by Charlie Gibbs. */
- /* */
- /*------------------------------------------------------------------*/
-
- #include <stdio.h>
- #include "a68kdef.h"
- #include "a68kglb.h"
-
- /* Functions */
- extern int LineParts(), GetField(), Instructions(), ObjDir();
- extern int GetSize(), ReadSymTab(), OpenIncl();
- extern long AddrBndW(), AddrBndL(), GetValue(), CalcValue();
- extern char *malloc();
- extern FILE *fopen();
-
- int GetArgs(), GetAReg(), GetInstModeSize(), GetMultReg();
-
-
-
- int GetArgs (name) char *name;
- /* Gets macro arguments and adds them to FNStack after adding "name".
- Returns the number of arguments added to the stack.
- Note that this might not be the full number of arguments
- provided if the stack overflowed. */
- {
- register int i, j, narg, instring;
- char currarg[MAXLINE]; /* Current argument */
-
- narg = 0; /* Argument counter */
-
- Heap2Space (strlen (name) + 1); /* Find space for name */
- strcpy (NextFNS, name); /* Add name to stack */
- NextFNS += strlen (name) + 1; /* Bump pointer */
- if (NextFNS > High2)
- High2 = NextFNS; /* Update high-water mark */
-
- i = SrcLoc; /* Now scan Line */
- while ((Line[i] != ' ') && (Line[i] != ';') && (Line[i] != '\0')) {
- j = 0;
- if (instring = (Line[i] == '<')) /* String delimiter */
- i++;
- while (1) {
- if (instring) {
- if (Line[i] == '>') {
- i++;
- break; /* End of string */
- }
- } else {
- if (Line[i] == '\0') break; /* End of line */
- if (Line[i] == ',') break; /* End of operand */
- if (Line[i] == ' ') break; /* End of all operands */
- if (Line[i] == ';') break; /* Start of comments */
- }
- currarg[j++] = Line[i++]; /* Get a character */
- }
- currarg[j] = '\0';
- Heap2Space (j + 1); /* Check for space */
- strcpy (NextFNS, currarg); /* Store argument */
- NextFNS += strlen (currarg) + 1; /* Next available space */
- if (NextFNS > High2)
- High2 = NextFNS; /* High-water mark */
- narg++; /* Count arguments */
- if (Line[i] == ',')
- i++; /* Skip over separator */
- }
- return (narg); /* Successful completion */
- }
-
-
-
- EffAdr (EA, Bad) struct OpConfig *EA; int Bad;
- /* Adds effective address field to Op (BITSET representing opcode) */
- {
- if ((1 << (EA->Mode - 1)) IN Bad) {
- Error (EA->Loc, ModeErr); /* Invalid mode */
- return;
- } else if (EA->Mode > 12) /* Special modes */
- return;
- else if (EA->Mode < 8) /* Register direct or indirect */
- Op |= ((EA->Mode - 1) << 3) | EA->Rn;
- else
- Op |= 0x0038 | (EA->Mode - 8); /* Absolute modes */
- OperExt (EA);
- }
-
-
-
- OperExt (EA) struct OpConfig *EA;
- /* Calculate operand Extension word, and check range of operands */
- {
- switch (EA->Mode) {
- case AbsL:
- break; /* No range checking needed */
- case AbsW:
- case ARDisp:
- case PCDisp:
- if ((EA->Value < -32768) || (EA->Value > 32767))
- Error (EA->Loc, SizeErr);
- break;
- case ARDisX:
- case PCDisX:
- if ((EA->Value < -128) || (EA->Value > 127))
- Error (EA->Loc, SizeErr);
- EA->Value &= 0x00FF; /* Displacement */
- EA->Value |= EA->Xn << 12; /* Index reg. */
- if (EA->X == Areg) EA->Value |= 0x8000; /* Addr. Reg. */
- if (EA->Xsize == Long) EA->Value |= 0x0800; /* Long reg. */
- break;
- case Imm:
- if (Size == Word) {
- if ((EA->Value < -32768) || (EA->Value > 65535L))
- Error (EA->Loc, SizeErr);
- } else if (Size == Byte)
- if ((EA->Value < -128) || (EA->Value > 255))
- Error (EA->Loc, SizeErr);
- break;
- }
- }
-
-
-
- GetOperand (oper, op) char oper[]; struct OpConfig *op;
- /* Finds mode and value for source or destination operand. */
- {
- register char ch;
- register int i, j;
- char UCoper[MAXLINE], tempop[MAXLINE];
- int rloc, MultFlag, opend;
-
- op->Value = op->Defn = 0;
- op->Mode = Null;
- op->X = X0;
- op->Hunk = ABSHUNK;
-
- if ((opend = strlen (oper) - 1) < 0)
- return; /* Nothing to process */
-
- for (i = 0; i <= opend; i++)
- UCoper[i] = toupper (oper[i]); /* Upper-case version */
- UCoper[i] = '\0';
-
- if (oper[0] == '#') { /* Immediate */
- strcpy (oper, &oper[1]);
- op->Value = GetValue (oper, op->Loc);
- op->Mode = Imm;
- op->Hunk = Hunk2;
- op->Defn = DefLine2;
- return;
- }
-
- i = IsRegister (oper, opend+1);
- if (i >= 0) {
- op->Mode = (i & 8) ? ARDir : DReg; /* Register type */
- op->Rn = i & 7; /* Register number */
- return;
- } else if (i == -2) {
- op->Mode = MultiM; /* Equated register list */
- op->Value = Sym->Val;
- return;
- } else if (strcmp (UCoper, "SP") == 0) {
- op->Mode = ARDir; /* Stack Pointer */
- op->Rn = 7; /* (it's A7) */
- return;
- } else if (strcmp (UCoper, "SR") == 0) {
- op->Mode = SR; /* Status Register */
- return;
- } else if (strcmp (UCoper, "CCR") == 0) {
- op->Mode = CCR; /* Condition Code Register */
- return;
- } else if (strcmp (UCoper, "USP") == 0) {
- op->Mode = USP; /* User Stack Pointer */
- return;
-
- } else if ((oper[0] == '(') && (oper[opend] == ')')) {
- i = IsRegister (&oper[1], opend-1);
- if (i >= 8 && i <= 15) {
- op->Mode = ARInd; /* Address Register indirect */
- op->Rn = i - 8;
- return;
- } else if (i > 0) {
- Error (op->Loc, AddrErr); /* Data register is invalid */
- return;
- } /* else may be parenthesized expression */
-
- } else if ((oper[0] == '(') /* Post-increment */
- && (oper[opend-1] == ')')
- && (oper[opend] == '+')) {
- op->Mode = ARPost;
- op->Rn = GetAReg (&oper[1], opend-2, op->Loc + 1);
- return;
-
- } else if ((oper[0] == '-') /* Pre-decrement */
- && (oper[1] == '(')
- && (oper[opend] == ')')) {
- i = IsRegister (&oper[2], opend-2);
- if (i >= 8 && i <= 15) {
- op->Mode = ARPre;
- op->Rn = i - 8;
- return;
- } else if (i > 0) {
- Error (op->Loc, AddrErr); /* Data register is invalid */
- return;
- } /* else parenthesized expression with leading minus? */
- }
-
- /* Try to split off displacement (if present).
- We'll assume we have a register expression if the operand
- ends with a parenthesized expression not preceded by an
- operator. I know this code is a real kludge, but that's
- the result of the bloody syntax. Thanks, Motorola. */
-
- j = strlen(oper) - 1; /* Last character */
- if (i = (oper[j] == ')')) /* Trailing parenthesis? */
- while (oper[--j] != '(') /* Find left parenthesis */
- if (j <= 0)
- break;
- if (j <= 0) /* Must not be at beginning */
- i = FALSE;
- if (i) {
- if (j == 1) {
- if (oper[0] == '-')
- i = FALSE; /* Leading minus sign */
- } else {
- if (oper[j-1] == '*') { /* Location counter? */
- if (!IsOperator (&oper[j-2]) || (oper[j-2] == ')'))
- i = FALSE; /* No, it's multiplication */
- } else if (IsOperator (&oper[j-1]) && (oper[j-1] != ')')) {
- i = FALSE; /* Preceded by an operator */
- }
- }
- }
-
- if (i) { /* Looks like a displacement mode */
- oper[j] = '\0';
- op->Value = GetValue (oper, op->Loc); /* Displacement */
- op->Hunk = Hunk2; /* Hunk number */
- op->Defn = DefLine2; /* Line where defined */
- oper[j++] = '('; /* Restore parenthesis */
-
- rloc = op->Loc + j; /* The register starts here */
- j = GetField (oper, j, tempop); /* Get address register */
- if (oper[j] == '\0') /* If there's no index register */
- tempop[strlen(tempop)-1] = '\0'; /* chop parenthesis */
-
- if ((tempop[2] == '\0')
- && (toupper (tempop[0]) == 'P')
- && (toupper (tempop[1]) == 'C')) {
- op->Mode = PCDisp; /* Program Counter */
- if (op->Hunk == CurrHunk) {
- op->Value -= (AddrCnt + 2); /* Adjust displacement */
- op->Hunk = ABSHUNK;
- }
- } else {
- op->Mode = ARDisp; /* Address Register */
- op->Rn = GetAReg (tempop, strlen (tempop), rloc);
- }
- if (oper[j] != '\0') { /* Index register is present */
- if (op->Mode == PCDisp)
- op->Mode = PCDisX; /* Program Counter indexed */
- else
- op->Mode = ARDisX; /* Address Register indexed */
- if (oper[j] != ',')
- Error (op->Loc, AddrErr); /* Bad separator */
- j++; /* Skip separator */
- rloc = op->Loc + j; /* Start of index */
- j = GetField (oper, j, tempop); /* Get index register */
- if (oper[j] == '\0')
- tempop[strlen(tempop)-1]='\0'; /* Chop parenthesis */
- else
- Error (rloc, AddrErr); /* It better be there */
-
- op->Xsize = GetSize (tempop); /* Index register size */
- if (op->Xsize == Byte) {
- Error (op->Loc+j-1, SizeErr); /* Must not be byte */
- op->Xsize = Word; /* Make it word for now */
- }
- i = IsRegister (tempop, strlen (tempop)); /* Get register */
- op->Xn = i & 7; /* Index register number */
- if ((i >= 0) && (i <= 7))
- op->X = Dreg; /* Data Register */
- else if ((i >= 8) && (i <= 15))
- op->X = Areg; /* Address Register */
- else
- Error (rloc, AddrErr); /* Invalid register */
- }
-
- if ((op->Hunk >= 0) && (op->Hunk != ABSHUNK))
- Error (op->Loc, RelErr); /* Relocatable displacement */
- return;
- }
-
- /* Check to see whether this could be a register list for MOVEM. */
- i = 0;
- MultFlag = FALSE;
- while(1) {
- if ((ch = UCoper[i++]) == '\0') {
- MultFlag = FALSE;
- break;
- }
- if ((ch == 'A') || (ch == 'D')) {
- ch = UCoper[i++];
- if (ch == '\0') {
- MultFlag = FALSE;
- break;
- }
- if ((ch >= '0') && (ch <= '7')) {
- ch = UCoper[i++];
- if (ch == '\0')
- break;
- if ((ch == '/') || (ch == '-'))
- MultFlag = TRUE;
- } else {
- MultFlag = FALSE;
- break;
- }
- } else {
- MultFlag = FALSE;
- break;
- }
- }
- if (MultFlag) {
- op->Mode = MultiM;
- op->Value = 0; /* We must still get the mask */
- return;
- }
-
- op->Value = GetValue (oper, op->Loc); /* Assume absolute mode */
- op->Hunk = Hunk2;
- op->Defn = DefLine2;
- if ((Hunk2 == ABSHUNK) && (DefLine2 <= LineCount)
- && (op->Value >= -32768) && (op->Value <= 32767))
- op->Mode = AbsW; /* Fits in a word */
- else
- op->Mode = AbsL;
- }
-
-
-
- int GetAReg (op, len, loc) char op[]; int len, loc;
- /* Validate an address register specification.
- Valid specifications are A0 through A7 , SP, or an EQUR label.
- The address register number will be returned if it is valid.
- Otherwise, Error will be called, using "loc" for the error
- location (this is its only use), and zero (A0) will be returned. */
- {
- register int i;
-
- i = IsRegister (op, len); /* Get register number */
- if ((i >= 8) && (i <= 15))
- return (i - 8); /* Valid address register */
- else {
- Error (loc, AddrErr); /* Not an address register */
- return (0); /* Set to A0 */
- }
- }
-
-
-
- int IsRegister (op, len) char op[]; int len;
- /* Check whether the current operand is an address or data register.
- Valid specifications are D0 throuth D7, A0 through A7, SP,
- or any symbol equated to a register with the EQUR directive.
- Return values:
- 0 through 7 - data registers 0 through 7 respectively
- 8 through 15 - address registers 0 through 7 respectively
- -1 - not a recognizable register
- -2 - Equated register list for MOVEM instruction (REG) */
- {
- char tempop[MAXLINE];
- register char *s;
- register int i;
-
- if (len == 2) { /* Two-character specification */
- i = toupper (op[0]);
- if ((i == 'S') && (toupper (op[1]) == 'P')) {
- return (15); /* Stack Pointer */
- } else if ((op[1] >= '0') && (op[1] <= '7')) {
- if (i == 'A') {
- return (op[1] - '0' + 8); /* Address Register */
- } else if (i == 'D') {
- return (op[1] - '0'); /* Data Register */
- }
- }
- }
- if (!GotEqur) /* If we have no EQURs to check */
- return (-1); /* don't waste any time here. */
- for (i = 0, s = op; i < len; i++) {
- if (IsOperator (s))
- return (-1); /* It sure isn't a label */
- tempop[i] = *s++;
- }
- tempop[i] = '\0';
- if (ReadSymTab (tempop)) {
- if (Sym->Flags & 0x60) {
- AddRef (LineCount); /* Found a register or list */
- return ((Sym->Flags & 0x20) ? (int) Sym->Val : -2);
- }
- }
- return (-1); /* Not a recognizable register */
- }
-
-
-
- int GetInstModeSize (Mode) int Mode;
- /* Determines the size for the various instruction modes. */
- {
- switch (Mode) {
- case ARDisp:
- case ARDisX:
- case PCDisp:
- case PCDisX:
- case AbsW:
- return (2);
- case AbsL:
- return (4);
- case MultiM:
- return (0); /* Accounted for by code generator */
- case Imm:
- if (Size == Long)
- return (4);
- else
- return (2);
- default:
- return (0);
- }
- }
-
-
-
- int GetMultReg (oper, predec, loc) char oper[]; int predec, loc;
- /* Builds a register mask for the MOVEM instruction */
- {
- register char ch;
- register int i, j;
- int T1, T2; /* Temporary variables for registers */
- int Range; /* We're processing a range of registers */
- int RegType; /* Register type (0=data, 1=address, 2=none) */
- int MultExt; /* The result is built here */
-
- MultExt = 0;
- Range = FALSE;
- RegType = 2;
- i = 0;
-
- ch = toupper (oper[i]);
- while (ch != '\0') {
- if (ch == 'A') {
- if (RegType == 2)
- RegType = 1; /* Address register */
- else {
- Error (loc, OperErr);
- return(0);
- }
- } else if (ch == 'D') {
- if (RegType == 2)
- RegType = 0; /* Data register */
- else {
- Error (loc, OperErr);
- return(0);
- }
- } else if ((ch >= '0') && (ch <= '7')) { /* Register number */
- if (RegType != 2) {
- T2 = (RegType * 8) + (ch - '0'); /* Bit number */
- if (predec)
- T2 = 15 - T2; /* Predecrement reverses mask */
- if (!Range) {
- MultExt |= (1 << T2); /* Single register */
- T1 = T2; /* Save number in case it's a range */
- } else { /* Range of registers */
- Range = FALSE;
- if (T1 > T2) {
- j = T1; /* Swap registers if backwards */
- T1 = T2;
- T2 = j;
- }
- for (j = T1; j <= T2; j++)
- MultExt |= (1 << j); /* Registers in range */
- }
- } else {
- Error (loc, OperErr);
- return(0);
- }
- } else if (ch == '-') { /* Range indicator */
- if ((Range == FALSE) && (RegType != 2) && (i > 0)) {
- RegType = 2;
- Range = TRUE;
- } else {
- Error (loc, OperErr);
- return(0);
- }
- } else if (ch == '/') { /* Separator */
- if ((Range == FALSE) && (RegType != 2) && (i > 0))
- RegType = 2;
- else {
- Error (loc, OperErr);
- return(0);
- }
- } else { /* Garbage */
- Error (loc, OperErr);
- return(0);
- }
- ch = toupper (oper[++i]);
- }
- return(MultExt);
- }
-